using Domain.Entities;
using Domain.Entities.Enums;
using NHibernate;
using System;
using System.Collections.Generic;
using System.Text;
using Domain.Misc;

namespace Domain.Services
{
    public static class TopicService
    {
        /*****************************************************************************************
        * Getters
        * ***************************************************************************************/
        public static Topic GetById(int topicId)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.Get<Topic>(topicId);
        }

        public static IList<Topic> GetTopicsByForum(Forum forum)
        {
            string query = String.Format(
                "from Topic topic where topic.Forum.Id = {0} order by topic.Type desc, topic.LastMessage.PostDateTime desc",
                forum.Id
            );
            return NHibernateHelper.ListQuery<Topic>(query);
        }

        public static IList<Topic> GetTopicsByForumPaged(Forum forum, int page, int topicsPerPage)
        {
            string query = String.Format(
                "from Topic topic where topic.Forum.Id = {0} order by topic.Type desc, topic.LastMessage.PostDateTime desc",
                forum.Id
            );
            return NHibernateHelper.QueryPaged<Topic>(query, page, topicsPerPage);
        }

        public static int GetTopicCountInForum(Forum forum)
        {
            string query = "select count(*) from Topic topic where topic.Forum.Id = " + forum.Id;
            return NHibernateHelper.CountQuery(query);
        }

        public static IList<Topic> GetTopicsWithPostsNewerThanOrAt(DateTime dateTime)
        {
            StringBuilder query = new StringBuilder();
            query.Append("from Topic topic where topic.LastMessage.PostDateTime >= '");
            query.Append(NHibernateHelper.ConvertDateTime(dateTime));
            query.Append("' order by topic.Type desc, topic.LastMessage.PostDateTime desc");
            ISession session = NHibernateHelper.Instance.CurrentSession;
            return session.CreateQuery(query.ToString()).List<Topic>();
        }

        public static int GetTotalNumberOfTopics()
        {
            string query = "select count(*) from Topic topic";
            return NHibernateHelper.CountQuery(query);
        }

        /*****************************************************************************************
        * Adders
        * ***************************************************************************************/
        public static Topic NewTopic(Forum forum, User poster, string subject, string text, TopicType type)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                Topic topic = new Topic();
                topic.Subject = subject;
                topic.Type = type;
                topic.PostDateTime = DateTime.Now;
                topic.Locked = false;
                topic.NumberOfReplies = 0;
                topic.Forum = forum;
                session.SaveOrUpdate(topic);

                Message message = new Message();
                message.Text = text;
                message.PostDateTime = DateTime.Now;
                message.Topic = topic;
                message.Poster = poster;
                message.Attachments = new List<Attachment>();
                session.SaveOrUpdate(message);

                topic.StartMessage = message;
                topic.LastMessage = message;
                session.SaveOrUpdate(topic);

                forum.NumberOfTopics++;
                forum.LastMessage = message;
                session.SaveOrUpdate(forum);

                poster.Posts++;
                session.SaveOrUpdate(poster);

                transaction.Commit();

                return topic;
            }
        }

        /*****************************************************************************************
        * Updaters
        * ***************************************************************************************/
        public static void UpdateTopic(Topic topic, string subject, string text, TopicType type)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                topic.Subject = subject;
                topic.Type = type;
                session.SaveOrUpdate(topic);

                topic.StartMessage.Text = text;
                session.SaveOrUpdate(topic.StartMessage);
                
                transaction.Commit();
            }
        }

        public static void LockTopic(Topic topic)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                topic.Locked = true;
                session.SaveOrUpdate(topic);
                
                transaction.Commit();
            }
        }

        public static void UnlockTopic(Topic topic)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                topic.Locked = false;
                session.SaveOrUpdate(topic);

                transaction.Commit();
            }
        }

        public static void MoveTopic(Topic topic, Forum newForum)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                Forum oldForum = topic.Forum;
                topic.Forum = newForum;
                oldForum.NumberOfTopics--;
                newForum.NumberOfTopics++;
                oldForum.NumberOfReplies -= topic.NumberOfReplies;
                newForum.NumberOfReplies += topic.NumberOfReplies;

                session.SaveOrUpdate(topic);
                session.SaveOrUpdate(oldForum);
                session.SaveOrUpdate(newForum);
                
                transaction.Commit();
            }
        }

        /*****************************************************************************************
        * Deleters
        * ***************************************************************************************/
        public static void RemoveTopic(Topic topic)
        {
            ISession session = NHibernateHelper.Instance.CurrentSession;
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Delete(topic);
                
                transaction.Commit();
            }
        }
    }
}
